import 'dart:convert';
import 'dart:io';

import 'package:m_todo/domain/entity/todo_entity.dart';
import 'package:m_todo/domain/store/base_todo_store.dart';
import 'package:m_todo/store/file_todo_util.dart';
import 'package:path/path.dart';

/// todoList文件存储
class FileTodoStore extends BaseTodoStore {
  final String dir;
  final String todoFileName;

  FileTodoStore({required this.dir, required this.todoFileName});

  @override
  Future<int> add(TodoEntity todoEntity) async {
    try {
      // 获取file
      File file = await _getStoreFile();
      // 加载todolist 到内存
      List<dynamic> todoList = await FileTodoUtil.loadTodoList(file);

      // 把新序列号保存到内存中
      int index = todoList.length + 1;
      todoEntity.index = index;
      todoList.add(todoEntity.toJson());

      // 把内存中todoList储存到file
      String todoListJsonStr = jsonEncode(todoList);
      await FileTodoUtil.saveStrToFile(file, todoListJsonStr);

      // 返回index
      return index;
    } catch (e) {
      return Future.error(e);
    }
  }

  @override
  Future<TodoEntity?> query(int index) async {
    var result = await _getStoreFile()
        .then((file) => FileTodoUtil.loadTodoList(file))
        .then((todoList) => todoList.firstWhere((element) => TodoEntity.fromJson(element).index == index))
        .catchError((e) => null);

    if (result != null) {
      return TodoEntity.fromJson(result);
    }
    return Future.value(null);
  }

  @override
  Future<List<TodoEntity>> queryAll() async {
    return _getStoreFile()
        .then((value) => FileTodoUtil.loadTodoList(value))
        .then((value) => value.map((e) => TodoEntity.fromJson(e)).toList())
        .catchError((e) => <TodoEntity>[]);
  }

  @override
  Future<List<TodoEntity>> queryUnDoneList() {
    return queryAll().then((value) => value.where((element) => element.state == TodoStateConst.unDone).toList()).catchError((e) => <TodoEntity>[]);
  }

  @override
  Future<void> update(TodoEntity todoEntity) async {
    List<TodoEntity> todoList = await queryAll();
    todoList.forEach((element) {
      if (element == todoEntity) {
        element.state = todoEntity.state;
        element.content = todoEntity.content;
      }
    });

    String todoListJsonStr = jsonEncode(todoList);
    await FileTodoUtil.saveStrToFile(await _getStoreFile(), todoListJsonStr);
  }

  /// 获取储存文件，如果不存在会新创建
  Future<File> _getStoreFile() async {
    var dire = Directory(dir);

    if (!await dire.exists()) {
      await dire.create();
    }

    File file = getStoreFile();

    if (!await file.exists()) {
      await file.create();
    }

    return file;
  }

  @override
  Future<String> export(String targetPath) async {
    try {
      // 创建目录
      var dir = Directory(targetPath);
      if (!await dir.exists()) {
        try {
          await dir.create(recursive: true);
        } catch (e) {
          return Future.error('文件路径无效：$targetPath');
        }
      }
      // 时间戳作为流水号
      var no = DateTime.now().microsecondsSinceEpoch;
      var targetFile = File(dir.path + '/' + 'todo$no.json');

      // 复制文件
      var storeFile = await _getStoreFile();
      await storeFile.copy(targetFile.path);

      // 返回完成路径
      return targetFile.absolute.path;
    } catch (e) {
      return Future.error(e);
    }
  }

  @override
  Future<int> import(String targetFilePath) async {
    try {
      var targetFile = File(targetFilePath);
      if (!await targetFile.exists()) {
        return Future.error('无效文件');
      }

      var newTodoList = await FileTodoUtil.loadTodoList(targetFile);
      if (newTodoList.isNotEmpty) {
        var coreFile = await _getStoreFile();
        // 合并两个列表
        var oldTodoList = await FileTodoUtil.loadTodoList(coreFile);
        oldTodoList.addAll(newTodoList);
        List<TodoEntity> mergeList = [];

        // 按照合并后的列表，重新生成index
        for (var i = 0; i < oldTodoList.length; i++) {
          var item = TodoEntity.fromJson(oldTodoList[i]);
          item.index = i + 1;
          mergeList.add(item);
        }

        await FileTodoUtil.saveStrToFile(coreFile, jsonEncode(mergeList));
      }

      return newTodoList.length;
    } catch (e) {
      return Future.error(e);
    }
  }

  /// 获取储存文件
  File getStoreFile() {
    return File(join(dir, todoFileName));
  }
}
